package com.lay.http.core;

import android.content.Context;
import android.support.v4.app.FragmentActivity;
import android.text.TextUtils;
import android.util.Log;

import com.lay.http.RequestFragment;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Map;

/**
 * Created by Administrator on 2019-11-13.
 */

public class DownloadRequest extends RequestBody {
    public static final int SPEED_NOT_LIMIT = 0;
    private int limitSpeed = SPEED_NOT_LIMIT;
    private long lastTime = 0;
    private boolean working = true;

    protected DownloadRequest(String url) {
        super(url);
    }

    public void setWorking(boolean working){
        this.working = working;
    }

    /**
     * 设置下载速度
     * @param limitSpeed 下载速度(K)
     */
    public DownloadRequest setLimitDownSpeed(int limitSpeed){
        limitSpeed = limitSpeed > SPEED_NOT_LIMIT ? limitSpeed : SPEED_NOT_LIMIT;
        this.limitSpeed = limitSpeed;
        return this;
    }


    @Override
    public ResponseBody send() {
        final DownloadResponse responseBody = new DownloadResponse();
        BufferedWriter writer = null;
        InputStream inputStream = null;
        try {
            String p = getParamString();
            HttpURLConnection connection = null;
            if(!TextUtils.isEmpty(p)){
                connection = (HttpURLConnection)new URL(url + "?" + p).openConnection();
            } else {
                connection = (HttpURLConnection)new URL(url).openConnection();
            }
            connection.setDoInput(true);
            connection.setConnectTimeout(getConnectTimeout());
            connection.setReadTimeout(getReadTimeout());
            connection.setRequestMethod("GET");
            for(Map.Entry<String, String> entry : getHeaders().entrySet()){
                connection.setRequestProperty(entry.getKey(), entry.getValue());
            }
            connection.connect();
            responseBody.setReaponseCode(connection.getResponseCode());
            responseBody.setHeader(connection.getHeaderFields());
            inputStream = connection.getInputStream();
            List<String> list = connection.getHeaderFields().get("Content-Length");
            String totleStr = null;
            if(list != null && !list.isEmpty()){
                totleStr = list.get(0);
            }
            final long totle;
            long totle1;
            try {
                totle1 = Long.parseLong(totleStr);
            } catch (Exception e){
                totle1 = 0;
            }
            totle = totle1;
            if(responseListener != null){
                if(getH() != null){
                    getH().post(new Runnable() {
                        @Override
                        public void run() {
                            responseListener.onPreProcess(totle);
                        }
                    });
                } else {
                    responseListener.onPreProcess(totle);
                }
            }
            final long finalTotle = totle;
            lastTime = System.currentTimeMillis();
            responseBody.handle(inputStream, new ResponseBody.ProcessListener() {
                @Override
                public boolean onProcess(final byte[] data, final long length){
                    if(limitSpeed > SPEED_NOT_LIMIT){
                        long now = System.currentTimeMillis();
                        long realTime = now - lastTime;
                        lastTime = now;
                        long limitTime = data.length / limitSpeed;
                        Log.d("TAG", "current:" + data.length + ", realTime:" + realTime + ", limitTime:" + limitTime);
                        if(realTime < limitTime){
                            try {
                                Thread.sleep(limitTime - realTime);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                    if(responseListener != null){
                        if(getH() != null){
                            getH().post(new Runnable() {
                                @Override
                                public void run() {
                                    responseListener.onProcess(data, length, finalTotle);
                                }
                            });
                        } else {
                            responseListener.onProcess(data, length, finalTotle);
                        }
                        if(!working){
                            responseBody.setReaponseCode(ResponseBody.CODE_DOWNLOAD_STOP);
                            // 如果绑定过context，需要在执行结束时，在fragment注销掉该回调
                            Context context = getBindContext();
                            if(context != null) {
                                if (context instanceof FragmentActivity) {
                                    android.support.v4.app.FragmentManager fm = ((FragmentActivity)context).getSupportFragmentManager();
                                    RequestFragment f = (RequestFragment)fm.findFragmentByTag(RequestFragment.FOR_HTTP);
                                    if(f != null){
                                        f.unregisteLifeRecycle(createTime);
                                        Log.d(RequestFragment.FOR_HTTP, "download stop -> " + DownloadRequest.this);
                                    }
                                }
                            }
                            return false;
                        } else {
                            return true;
                        }
                    } else {
                        return false;
                    }
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
            responseBody.setReaponseCode(ResponseBody.CODE_CONNECTED_ERROR);
        } finally {
            if(writer != null){
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return responseBody;
    }

    private String getParamString(){
        StringBuilder sb = new StringBuilder();
        for(Map.Entry<String, Object> entry : getParams().entrySet()){
            sb.append("&").append(entry.getKey()).append("=").append(entry.getValue());
        }
        if(sb.length() > 0){
            sb.deleteCharAt(0);
        }
        return sb.toString();
    }
}
